home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / ghostscript / gs_fonts.ps < prev    next >
Text File  |  1994-08-01  |  17KB  |  538 lines

  1. %    Copyright (C) 1990, 1992, 1993 Aladdin Enterprises.  All rights reserved.
  2. %
  3. % This file is part of Ghostscript.
  4. %
  5. % Ghostscript is distributed in the hope that it will be useful, but
  6. % WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  7. % to anyone for the consequences of using it or for whether it serves any
  8. % particular purpose or works at all, unless he says so in writing.  Refer
  9. % to the Ghostscript General Public License for full details.
  10. %
  11. % Everyone is granted permission to copy, modify and redistribute
  12. % Ghostscript, but only under the conditions described in the Ghostscript
  13. % General Public License.  A copy of this license is supposed to have been
  14. % given to you along with Ghostscript so you can know your rights and
  15. % responsibilities.  It should be in a file named COPYING.  Among other
  16. % things, the copyright notice and this notice must be preserved on all
  17. % copies.
  18.  
  19. % Font initialization for Ghostscript.
  20.  
  21. % The standard representation for PostScript compatible fonts is described
  22. % in the book "Adobe Type 1 Font Format", published by Adobe Systems Inc.
  23. % We don't attempt to document this representation here.
  24. % Ghostscript uses Type 1 fonts, except that the external form doesn't use
  25. % eexec encryption and may not even use CharString encryption.
  26.  
  27.  
  28. % Define the default font.
  29. /defaultfontname /Ugly def
  30.  
  31. % Load the font name -> font file name map.
  32. userdict /Fontmap FontDirectory maxlength dict put
  33. /.loadFontmap        % <filename>
  34.  { 2 dict begin
  35.      mark Fontmap
  36.      /;
  37.       { % The stack contains a mark, the dictionary, the font name,
  38.         % the file or alias name, and possibly additional information
  39.     % about the font.
  40.     counttomark 3 sub { pop } repeat .growput
  41.     Fontmap
  42.       } bind def
  43.      3 -1 roll run
  44.    end
  45.    pop pop        % pop the mark and the copy of the dictionary
  46.  } bind def
  47. (Fontmap) .loadFontmap
  48.  
  49. % Ghostscript optionally can load individual CharStrings as they are needed.
  50. % (This is intended primarily for machines with very small memories.)
  51. % This happens if DISKFONTS is true.  In this case, we define another
  52. % dictionary parallel to FontDirectory that retains an open file
  53. % for every font loaded.
  54. /FontFileDirectory 10 dict def
  55.  
  56. % Define an augmented version of .buildfont1 that inserts UnderlinePosition
  57. % and UnderlineThickness entries in FontInfo if they aren't there already.
  58. % (This works around the incorrect assumption, made by many word processors,
  59. % that these entries are present in the built-in fonts.)
  60. /.buildfont1x
  61.  { dup /FontInfo known not
  62.     { dup /FontInfo 2 dict .growput }
  63.    if
  64.    dup dup /FontInfo get dup dup
  65.    /UnderlinePosition known exch /UnderlineThickness known and
  66.     { pop pop        % entries already present
  67.     }
  68.     { dup length 2 add dict copy
  69.       dup /UnderlinePosition known not
  70.        { dup /UnderlinePosition 3 index /FontBBox get
  71.          1 get 2 div put        % 1/2 the font descent
  72.        }
  73.       if
  74.       dup /UnderlineThickness known not
  75.        { dup /UnderlineThickness 3 index /FontBBox get
  76.          dup 3 get exch 1 get sub 20 div put    % 1/20 the font height
  77.        }
  78.       if
  79.       1 index /FontInfo get wcheck not { readonly } if
  80.       /FontInfo exch put
  81.     }
  82.    ifelse .buildfont1
  83.  } bind def
  84. % Define definefont.  This is a procedure built on a set of operators
  85. % that do all the error checking and key insertion.
  86. mark
  87.     /.buildfont0 where { pop 0 /.buildfont0 load } if
  88.     /.buildfont1 where { pop 1 /.buildfont1x load } if
  89.     /.buildfont3 where { pop 3 /.buildfont3 load } if
  90. .dicttomark /.buildfontdict exch def
  91. /definefont
  92.  { 1 dict begin count /d exch def    % save stack depth in case of error
  93.     {        % Check for disabled platform fonts.
  94.       NOPLATFONTS
  95.        { dup maxlength 1 index length sub 2 lt { dup .growdict } if
  96.      dup /ExactSize 0 put
  97.        }
  98.        {    % Hack: if the Encoding looks like it might be the
  99.         % Symbol or Dingbats encoding, load those now (for the
  100.         % benefit of platform font matching) just in case
  101.         % the font didn't actually reference them.
  102.      dup /Encoding get length 65 ge
  103.       { dup /Encoding get 64 get
  104.         dup /congruent eq { SymbolEncoding pop } if
  105.         /a9 eq { DingbatsEncoding pop } if
  106.       }
  107.      if
  108.        }
  109.       ifelse
  110.       dup /FontType get //.buildfontdict exch get exec
  111.       DISKFONTS
  112.        { FontFileDirectory 2 index known
  113.           { dup /FontFile FontFileDirectory 4 index get .growput
  114.       }
  115.      if
  116.        }
  117.       if
  118.       readonly
  119.     }
  120.    stopped
  121.     { count d sub { pop } repeat end /invalidfont signalerror }
  122.     { end dup FontDirectory 4 2 roll .growput }
  123.    ifelse
  124.  } odef
  125.  
  126.  
  127. % Ghostscript optionally can load individual CharStrings as they are needed.
  128. % (This is intended primarily for machines with very small memories.)
  129. % Initially, the character definition is the file position of the definition;
  130. % this gets replaced with the actual CharString.
  131. % Note that if we are loading characters lazily, CharStrings is writable.
  132.  
  133. % _Cstring must be long enough to hold the longest CharString for
  134. % a character defined using seac.  This is lenIV + 4 * 5 (for the operands
  135. % of sbw, assuming div is not used) + 2 (for sbw) + 3 * 5 (for the operands
  136. % of seac other than the character codes) + 2 * 2 (for the character codes)
  137. % + 2 (for seac), i.e., lenIV + 43.
  138.  
  139. /_Cstring 60 string def
  140.  
  141. % When we initially load the font, we call
  142. %    <index|charname> <length> <readproc> cskip_C
  143. % to skip over each character definition and return the file position instead.
  144. % This substitutes for the procedure
  145. %    <index|charname> <length> string currentfile exch read[hex]string pop
  146. %      [encrypt]
  147. % What we actually store is fileposition * 1000 + length,
  148. %   negated if the string is stored in binary form.
  149.  
  150. % Older fonts use skip_C rather than cskip_C.
  151. % skip_C takes /readstring or /readhexstring as its third argument,
  152. % instead of the entire reading procedure.
  153. /skipproc_C {string currentfile exch readstring pop} cvlit def
  154. /skip_C
  155.  { //skipproc_C dup 3 4 -1 roll put cvx readonly cskip_C
  156.  } bind def
  157. /cskip_C
  158.  { exch dup 1000 ge 3 index type /nametype ne or
  159.     { % This is a Subrs string, or the string is so long we can't represent
  160.       % its length.  Load it now.
  161.       exch exec
  162.     }
  163.     { % Record the position and length, and skip the string.
  164.       dup currentfile fileposition 1000 mul add
  165.       2 index 3 get /readstring cvx eq { neg } if
  166.       3 1 roll
  167.       dup _Cstring length idiv
  168.        { currentfile _Cstring 3 index 3 get exec pop pop
  169.        } repeat
  170.       _Cstring length mod _Cstring exch 0 exch getinterval
  171.       currentfile exch 3 -1 roll 3 get exec pop pop
  172.     }
  173.    ifelse
  174.  } bind def
  175.  
  176. % Type1BuildGlyph calls load_C to actually load the character definition.
  177.  
  178. /load_C        % <charname> <fileposandlength> -> -
  179.  { dup abs 1000 idiv FontFile exch setfileposition
  180.    CharStrings 3 1 roll
  181.    dup 0 lt
  182.     { neg 1000 mod string FontFile exch readstring }
  183.     { 1000 mod string FontFile exch readhexstring }
  184.    ifelse pop
  185. % If the CharStrings aren't encrypted on the file, encrypt now.
  186.    Private /-| get 0 get
  187.    dup type /nametype ne { dup length 5 sub 5 exch getinterval exec } { pop } ifelse
  188.    dup 4 1 roll put
  189. % If the character is defined with seac, load its components now.
  190.    mark exch seac_C
  191.    counttomark
  192.     { StandardEncoding exch get dup CharStrings exch get
  193.       dup type /integertype eq { load_C } { pop pop } ifelse
  194.     } repeat
  195.    pop        % the mark
  196.  } bind def
  197.  
  198. /seac_C        % charstring -> achar bchar ..or nothing..
  199.  { dup length _Cstring length le
  200.     { 4330 exch _Cstring .type1decrypt exch pop
  201.       dup dup length 2 sub 2 getinterval <0c06> eq    % seac
  202.        { dup length
  203.          Private /lenIV known { Private /lenIV get } { 4 } ifelse
  204.      exch 1 index sub getinterval
  205. % Parse the string just enough to extract the seac information.
  206. % We assume that the only possible operators are hsbw, sbw, and seac,
  207. % and that there are no 5-byte numbers.
  208.      mark 0 3 -1 roll
  209.       { exch
  210.          { { dup 32 lt
  211.               { pop 0 }
  212.           { dup 247 lt
  213.              { 139 sub 0 }
  214.              { dup 251 lt
  215.             { 247 sub 256 mul 108 add 1 1 }
  216.             { 251 sub -256 mul -108 add -1 1 }
  217.                ifelse
  218.              }
  219.             ifelse
  220.           }
  221.          ifelse
  222.            }            % 0
  223.            { mul add 0 }        % 1
  224.          }
  225.         exch get exec
  226.       }
  227.      forall pop
  228.      counttomark 1 add 2 roll cleartomark    % pop all but achar bchar
  229.        }
  230.        { pop    % not seac
  231.        }
  232.       ifelse
  233.     }
  234.     { pop    % punt
  235.     }
  236.    ifelse
  237.  } bind def
  238.  
  239. % Define an auxiliary procedure for loading a font.
  240. % If DISKFONTS is true and the body of the font is not encrypted with eexec:
  241. %    - Prevent the CharStrings from being made read-only.
  242. %    - Substitute a different CharString-reading procedure.
  243. % (eexec disables this because the implicit 'systemdict begin' hides
  244. % the redefinitions that make the scheme work.)
  245. % We assume that:
  246. %    - The magic procedures (-|, -!, |-, and |) are defined with
  247. %    executeonly or readonly;
  248. %    - The contents of the reading procedures are as defined in bdftops.ps;
  249. %    - The font ends with
  250. %    <font> <Private> <CharStrings>
  251. %    readonly put noaccess|readonly put
  252. 4 dict begin
  253.  /dict            % leave room for FontFile
  254.   { 1 add dict
  255.   } bind def
  256.  /executeonly        % for reading procedures
  257.   { readonly
  258.   } def
  259.  /noaccess        % for Subrs strings and Private dictionary
  260.   { readonly
  261.   } def
  262.  /readonly        % for procedures and CharStrings dictionary
  263.   {    % We want to take the following non-standard actions here:
  264.       %   - If the operand is the CharStrings dictionary, do nothing;
  265.     %   - If the operand is a number (a file position replacing the
  266.     %    actual CharString), do nothing;
  267.     %   - If the operand is either of the reading procedures (-| or -!),
  268.     %    substitute a different one.
  269.     dup type /dicttype eq        % CharStrings or Private
  270.      { 1 index /CharStrings ne { readonly } if }
  271.      { dup type /arraytype eq        % procedure or data array
  272.         { dup length 5 ge 1 index xcheck and
  273.        { dup 0 get /string eq
  274.          1 index 1 get /currentfile eq and
  275.          1 index 2 get /exch eq and
  276.          1 index 3 get dup /readstring eq exch /readhexstring eq or and
  277.          1 index 4 get /pop eq and
  278.           { /cskip_C cvx 2 packedarray cvx
  279.           }
  280.           { readonly
  281.           }
  282.          ifelse
  283.        }
  284.        { readonly
  285.        }
  286.       ifelse
  287.     }
  288.     { dup type /stringtype eq    % must be a Subr string
  289.        { readonly }
  290.       if
  291.     }
  292.        ifelse
  293.      }
  294.     ifelse
  295.   } bind def
  296. currentdict end readonly /.loadfontdict exch def
  297. /.loadfont        % <file> .loadfont ->
  298.  { mark exch systemdict begin
  299.    DISKFONTS { .loadfontdict begin } if
  300.    % We really would just like systemdict on the stack,
  301.    % but fonts produced by Fontographer require a writable dictionary....
  302.    8 dict begin        % garbage
  303.     % We can't just use `run', because we want to check for
  304.     % .PFB files.  We can't save the packing status anywhere,
  305.     % so we need two separate control paths.
  306.     % Also, we would like to use `false /PFBDecode filter',
  307.     % but this occasionally produces a whitespace character as
  308.     % the first of an eexec section, so we can't do it.
  309.     % Finally, since the interpreter doesn't currently automatically
  310.     % close an input file when the file reaches EOF (unless it's
  311.     % the interpreter's current input file), we must explicitly
  312.     % close the real file if we used a PFB filter.
  313.    currentpacking
  314.     { false setpacking
  315.        { dup read not { -1 } if
  316.          2 copy unread 16#80 eq
  317.       { dup true /PFBDecode filter cvx exec closefile }
  318.       { cvx exec }
  319.      ifelse
  320.        } stopped    % split up `execute'
  321.       true setpacking
  322.       $error /newerror get and {handleerror} if
  323.     }
  324.     {  { dup read not { -1 } if
  325.          2 copy unread 16#80 eq
  326.       { dup true /PFBDecode filter cvx exec closefile }
  327.       { cvx exec }
  328.      ifelse
  329.        } execute
  330.     }
  331.    ifelse
  332.    DISKFONTS { end } if
  333.    end end cleartomark
  334.  } bind def
  335.  
  336. % Define a procedure for defining aliased fonts.
  337. % We just copy the original font, changing the FontName.
  338. /.aliasfont        % <name> <font> -> <newFont>
  339.  { dup length 2 add dict
  340.    dup 3 -1 roll { 1 index /FID eq { pop pop } { put dup } ifelse } forall
  341.    /FontName 3 index put
  342.    definefont
  343.  } odef % bind def
  344.  
  345. % Define findfont so it tries to load a font if it's not found.
  346. /findfont
  347.  {    % Since PostScript has no concept of goto, or even blocks with
  348.     % exits, we use a loop as a way to get an exitable scope.
  349.     % The loop is never executed more than twice.
  350.     {
  351.     dup FontDirectory exch known        % Already loaded?
  352.      { FontDirectory exch get exit }
  353.     if
  354.  
  355.     dup Fontmap exch known not    % Unknown font name.
  356.      { dup defaultfontname eq
  357.         { (Default font ) print cvx =only
  358.           ( not found in Fontmap!  Giving up.\n) print flush
  359.           1 .quit
  360.         } if
  361.        QUIET not
  362.         { (Substituting ) print defaultfontname cvx =only
  363.           ( for unknown font ) print dup == flush
  364.         } if
  365.        defaultfontname findfont .aliasfont exit
  366.      }
  367.     if
  368.  
  369.     dup Fontmap exch get
  370.  
  371.     % Check for a font alias.
  372.     dup type /nametype eq
  373.      { findfont .aliasfont exit
  374.      }
  375.     if
  376.  
  377.     % If we can't open the file, substitute for the font.
  378.     findlibfile
  379.      { % Stack: fontname fontfilename fontfile
  380.        DISKFONTS
  381.         { 1 index (r) file
  382.           FontFileDirectory exch 4 index exch .growput
  383.         }
  384.        if
  385.        QUIET not
  386.         { (Loading ) print 2 index =only
  387.           ( font from ) print exch print (... ) print flush }
  388.         { exch pop }
  389.        ifelse
  390.        .loadfont
  391.        QUIET not
  392.         { vmstatus 3 { =only ( ) print } repeat
  393.           (done.\n) print flush
  394.         } if
  395.        % Check to make sure the font was actually loaded.
  396.        dup FontDirectory exch known { findfont exit } if
  397.  
  398.        (Loading ) print dup cvx =only
  399.        ( font failed, substituting ) print defaultfontname cvx =only
  400.        (.\n) print flush
  401.        defaultfontname findfont .aliasfont exit
  402.      }
  403.     if
  404.  
  405.     % findlibfile failed, substitute the default font.
  406.     % Stack: fontname fontfilename
  407.     (Can't find \(or can't open\) font file ) print print
  408.     dup defaultfontname eq
  409.      { ( for default font \() print cvx =only
  410.        (\)!  Giving up.\n) print flush 1 .quit
  411.      }
  412.      { ( for font ) print dup cvx =only
  413.        (, substituting ) print defaultfontname cvx =only
  414.        (.\n) print flush
  415.        defaultfontname findfont .aliasfont
  416.      }
  417.     ifelse
  418.     exit
  419.  
  420.     } loop        % end of loop
  421.  
  422.  } odef % bind def
  423.  
  424.  
  425. % The CharStrings are a dictionary in which the key is the character name,
  426. % and the value is a compressed and encrypted representation of a path.
  427. % For detailed information, see the book "Adobe Type 1 Font Format",
  428. % published by Adobe Systems Inc.
  429.  
  430. % Here are the BuildChar and BuildGlyph implementation for Type 1 fonts.
  431. % The names Type1BuildChar and Type1BuildGlyph are known to the interpreter.
  432.  
  433. /Type1BuildChar
  434.  { 1 index /Encoding get exch get Type1BuildGlyph
  435.  } bind def
  436. /Type1BuildGlyph
  437.  { exch begin
  438.     dup CharStrings exch .knownget not
  439.      { QUIET not
  440.         { (Substituting .notdef for ) print = flush
  441.     } { pop } ifelse
  442.        /.notdef CharStrings /.notdef get
  443.      } if
  444.     % stack: charname charstring
  445.     PaintType 0 ne
  446.      { 1 setmiterlimit 1 setlinejoin 1 setlinecap
  447.        currentdict /StrokeWidth .knownget not { 0 } if
  448.        setlinewidth
  449.      } if
  450.     dup type /stringtype eq        % encoded outline
  451.      { outline_C
  452.      }
  453.      { dup type /integertype eq        % file position for lazy loading
  454.         { 1 index exch load_C dup CharStrings exch get outline_C
  455.     }
  456.     {                % PostScript procedure
  457.       currentdict end systemdict begin begin   exec   end
  458.     }
  459.        ifelse
  460.      }
  461.     ifelse
  462.    end
  463.  } bind def
  464.  
  465. % Make the call on setcachedevice a separate procedure,
  466. % so we can redefine it if the composite font extensions are present.
  467. % (We don't use the obvious
  468. %    /setcachedevice_C /setcachedevice load def
  469. % because that would bind it into outline_C.)
  470. /setcachedevice_C { setcachedevice } bind def
  471.  
  472. /outline_C        % <charname> <charstring> -> -
  473.  { currentdict /Metrics .knownget
  474.     { 2 index .knownget
  475.        { dup type dup /integertype eq exch /realtype eq or
  476.           {    % <wx>
  477.         exch .type1addpath 0
  478.       }
  479.       { dup length 2 eq
  480.          {    % [<wx> <sbx>]
  481.            exch 1 index 0 get 0 .type1addpath
  482.            1 get 0
  483.          }
  484.          {    % [<wx> <wy> <sbx> <sby>]
  485.            aload pop 5 -1 roll 3 1 roll .type1addpath
  486.          }
  487.         ifelse
  488.       }
  489.      ifelse
  490.        }
  491.        { .type1addpath currentpoint
  492.        }
  493.       ifelse
  494.     }
  495.     { .type1addpath currentpoint
  496.     }
  497.    ifelse        % stack: wx wy
  498.    pathbbox
  499.    PaintType 0 ne
  500.     {        % Expand the bounding box by the stroke width.
  501.         % (Actually, only half the stroke width is needed.)
  502.       4 -1 roll currentlinewidth sub
  503.       4 -1 roll currentlinewidth sub
  504.       4 -1 roll currentlinewidth add
  505.       4 -1 roll currentlinewidth add
  506.     }
  507.    if
  508.    setcachedevice_C
  509.    PaintType 0 eq { fill } { stroke } ifelse
  510.    pop
  511.  } bind def
  512.  
  513. % Find all the precompiled font operators in systemdict.
  514.    systemdict
  515.     { exch =string cvs (.font_) anchorsearch
  516.        { pop pop exec    % execute the operator, returns the font dictionary
  517.          dup begin
  518.        Encoding type /stringtype eq
  519.         { Encoding cvn cvx exec /Encoding exch def
  520.         }
  521.        if
  522.        FontName exch
  523.      end definefont pop
  524.        }
  525.        { pop pop
  526.        }
  527.       ifelse
  528.     }
  529.    forall
  530.  
  531.  
  532.  
  533. % Define a procedure to load all known fonts.
  534. % This isn't likely to be very useful.
  535. /loadallfonts
  536.  { Fontmap { pop findfont pop } forall
  537.  } bind def
  538.